package com.isman.placeslist.ws;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

import com.isman.placeslist.ws.CustomMultiPartEntity.ProgressListener;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;

public class AsyncRunner extends AsyncTask<Void, Integer, Void> {
	private int mMethod;
	private String mPath;
	private Bundle mBundle;
	private Context mContext;
	private AsyncRunnerHeadler mHeadler;
	private ProgressDialog mProgressDialog;
	private long totalSize;

	public static final int GET = 0;
	public static final int POST = 1;
	public static final int PUT = 2;
	public static final int DELETE = 3;

	private static final String TAG = "AsyncRunner";

	public AsyncRunner(Context context) {
		this.mContext = context;
	}

	public void exe(String path, Bundle bundle, int method,
			AsyncRunnerHeadler headler) {
		this.mPath = path;
		this.mBundle = bundle;
		this.mMethod = method;
		this.mHeadler = headler;
	}

	public void exe(String path, AsyncRunnerHeadler headler) {
		this.mPath = path;
		this.mMethod = GET;
		this.mHeadler = headler;
	}

	public void exe(String path, Bundle bundle, int method,
			ProgressDialog progressDialog, AsyncRunnerHeadler headler) {
		this.mPath = path;
		this.mBundle = bundle;
		this.mMethod = method;
		this.mHeadler = headler;
		this.mProgressDialog = progressDialog;
	}

	@Override
	protected Void doInBackground(Void... params) {
		HttpResponse response = null;
		RESTClient client = new RESTClient(mContext, mHeadler);

		switch (mMethod) {
		case GET:
			Log.i("AsyncRunner", "GET");
			response = client.Get(mPath);
			break;
		case POST:
			Log.i("AsyncRunner", "POST");

			CustomMultiPartEntity entity = new CustomMultiPartEntity(
					new ProgressListener() {
						@Override
						public void transferred(long num) {
							publishProgress((int) ((num / (float) totalSize) * 100));
						}
					});
			if (mBundle.containsKey("image")) {
				File file = new File(mBundle.getString("image"));
				if (file.exists()) {
					ContentBody cbFile = new FileBody(file, "image/jpeg");
					entity.addPart("image", cbFile);
					totalSize = entity.getContentLength();
					mBundle.remove("image");
				}
			}
			File fileTemp = null;
			if (mBundle.containsKey("image-temp")) {
				fileTemp = new File(mBundle.getString("image-temp"));
				if (fileTemp.exists()) {
					ContentBody cbFile = new FileBody(fileTemp, "image/jpeg");
					entity.addPart("image", cbFile);
					totalSize = entity.getContentLength();
					mBundle.remove("image-temp");
				}
			}

			for (String key : mBundle.keySet()) {
				try {
					entity.addPart(key, new StringBody(mBundle.getString(key)
							+ ""));
					Log.i(TAG,
							"Key " + key + " value " + mBundle.getString(key)
									+ "");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
			response = client.Post(mPath, entity);

			if (fileTemp != null) {
				if (fileTemp.exists()) {
					fileTemp.delete();
				}
			}
			break;
		case PUT:
			Log.i("AsyncRunner", "PUT");
			response = client.Put(mPath, mBundle);
			break;
		case DELETE:
			Log.i("AsyncRunner", "DELETE");
			response = client.Delete(mPath);
			break;
		}
		if (response == null) {
			Looper.prepare();
			mHeadler.onError(404, "Internet connection lost.");
			Looper.loop();
			return null;
		}

		int httpStauts = response.getStatusLine().getStatusCode();
		if (httpStauts == HttpStatus.SC_OK) {
			try {
				mHeadler.onComplete(read(response.getEntity().getContent()));
			} catch (Exception e) {
				e.printStackTrace();
				mHeadler.onConnectingError(e.getMessage());
			}
		} else if (httpStauts == HttpStatus.SC_FORBIDDEN) {
			Looper.prepare();
			try {
				mHeadler.onAuthenticate(read(response.getEntity().getContent()));
			} catch (Exception e) {
				mHeadler.onConnectingError(e.getMessage());
				e.printStackTrace();
			}
			Looper.loop();
		} else {
			Looper.prepare();
			try {
				mHeadler.onError(httpStauts, read(response.getEntity()
						.getContent()));
			} catch (Exception e) {
				mHeadler.onConnectingError(e.getMessage());
				e.printStackTrace();
			}
			Looper.loop();
		}
		return null;
	}

	@Override
	protected void onPostExecute(Void result) {
		if (mProgressDialog != null) {
			mProgressDialog.dismiss();
		} else {
			super.onPostExecute(result);
		}
	}

	@Override
	protected void onPreExecute() {
		if (mProgressDialog != null) {
			mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			mProgressDialog.setMessage("Uploading Picture...");
			mProgressDialog.setCancelable(false);
			mProgressDialog.show();
		} else {
			super.onPreExecute();
		}
	}

	@Override
	protected void onProgressUpdate(Integer... progress) {
		if (mProgressDialog != null) {
			mProgressDialog.setProgress((int) (progress[0]));
		} else {
			super.onProgressUpdate(progress);
		}
	}

	private String read(InputStream inputStream) throws IOException {
		if (inputStream != null) {
			StringBuilder sb = new StringBuilder();
			String line;
			try {
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(inputStream, "UTF-8"));
				while ((line = reader.readLine()) != null) {
					sb.append(line).append("\n");
				}
			} finally {
				inputStream.close();
			}
			return sb.toString();
		} else {
			return "";
		}
	}
}
